﻿using System;
using System.Collections.Generic;
using System.Windows.Controls.Primitives;
using GalaSoft.MvvmLight.Messaging;
using Holdem.Core.Controls;
using Holdem.Interfaces;
using Holdem.Interfaces.Card;
using Holdem.Interfaces.Configuration;
using Holdem.Interfaces.Extensions;
using Holdem.Interfaces.HandHistory;
using Holdem.Interfaces.Messages;
using Holdem.Interfaces.Service;
using Holdem.Interfaces.ViewModel;
using Holdem.Service;

using Microsoft.Phone.Reactive;
using Microsoft.Phone.Shell;

namespace TexasHoldemCalculator.View
{
    public partial class CalculatorView
    {
        #region Variables

        private static bool _loaded;
        private Popup _popup;

        #endregion

        #region Properties

        private static IDictionary<string, object> PhoneState
        {
            get
            {
                return PhoneApplicationService.Current.State;
            }
        }

        private IHoldemPhoneConfiguration Configuration
        {
            get
            {
                return Factory.Instance.GetInstance<IConfigurationService>().PersistentConfiguration;
            }
        }

        private IAdProvider AdProvider
        {
            get
            {
                return Factory.Instance.GetInstance<IAdProvider>();
            }
        }

        #endregion //Properties

        #region Constructor

        public CalculatorView()
        {
            if (PhoneState.ContainsKey("Loaded"))
                _loaded = (bool)PhoneState["Loaded"];

            if (!_loaded)
                this.ShowPopup();
            else
            {
                this.InitializeComponent();
                this.SetAdInformation();
                this.AddEventHandlers();
            }
        }

        private void SetAdInformation()
        {
            this.THCStatisticsAd.AdUnitId = AdProvider.AdUnitId;
            this.THCStatisticsAd.ApplicationId = AdProvider.ApplicationId;
        }

        private void AddEventHandlers()
        {
            var viewModel = Factory.Instance.GetInstance<IHoldemCalculatorViewModel>();

            Messenger.Default.Register<RoundGeneratedMessage>(
                this, m => StartVerticalAnimation(m.Data));

            Messenger.Default.Register<DeckGeneratedMessage>(
                this, m => StartFadInOutAnimation(m.Data));

            Messenger.Default.Register<HandGeneratedRoundMessage>(
                this, m => StartHorizontalAnimation(m.Data));
        }

        #endregion //Constructor

        #region Private Methods

        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            //var viewModel = Factory.Instance.GetInstance<IHoldemCalculatorViewModel>();

            //viewModel.RoundGenerated -= StartVerticalAnimation;
            //viewModel.HoldemHandGenerated -= StartFadInOutAnimation;
            //viewModel.HoldemHandRoundGenerated -= StartHorizontalAnimation;
        }

        private void ShowPopup()
        {
            _popup =
                new Popup
                {
                    Child = new SplashPopup(),
                    IsOpen = true
                };

            StartLoadingData();
        }

        private void StartLoadingData()
        {
            if( _loaded )
                return;

            Scheduler.Dispatcher.Schedule(
                () =>
                {
                    if( _loaded )
                        return;

                    this.InitializeComponent();
                    this.SetAdInformation();
                    this.AddEventHandlers();

                    Scheduler.Dispatcher.Schedule(
                        this.ClosePop,
                        TimeSpan.FromSeconds(2));
                });
        }

        private void ClosePop()
        {
            _loaded = true;
            _popup.IsOpen = false;

            PhoneState["Loaded"] = _loaded;

            this.ApplicationBar.IsVisible = true;
        }

        private void StartFadInOutAnimation(History history)
        {
            if( !Configuration.Cast<bool>(ConfigKey.HoldemOptoinsViewCardAnimations) )
                return;

            this.HoldemHoleCardsControl.AnimateCardImageOne();
            this.HoldemHoleCardsControl.AnimateCardImageTwo();
        }

        private void StartVerticalAnimation(HoldemCard round)
        {
            AnimateCards(round, true);
        }

        private void StartHorizontalAnimation(HoldemCard round)
        {
            AnimateCards(round, false);
        }

        private void AnimateCards(HoldemCard round, bool vertical)
        {
            if (!Configuration.Cast<bool>(ConfigKey.HoldemOptoinsViewCardAnimations))
                return;

            this.FlopHandsStackPanel.IsVerticalAnimation = vertical;

            if (round >= HoldemCard.River)
                this.AnimateFlopToRiver();
            else if (round >= HoldemCard.Turn)
                this.AnimateFlopToTurn();
            else if (round >= HoldemCard.Flop3 || round == HoldemCard.Flop1)
                this.AnimateFlop();
        }

        #region Animation Orchestrations

        private void AnimateFlop()
        {
            this.DominoAnimate(
                () => this.FlopHandsStackPanel.AnimateCardImageOne(),
                () => this.DominoAnimate(
                    () => this.FlopHandsStackPanel.AnimateCardImageTwo(),
                    () => this.FlopHandsStackPanel.AnimateCardImageThree()));
        }

        private void AnimateFlopToTurn()
        {
            this.DominoAnimate(
                () => this.FlopHandsStackPanel.AnimateCardImageOne(),
                () => this.DominoAnimate(
                    () => this.FlopHandsStackPanel.AnimateCardImageTwo(),
                    () => this.DominoAnimate(
                        () => FlopHandsStackPanel.AnimateCardImageThree(),
                        () => FlopHandsStackPanel.AnimateCardImageFour())));
        }

        private void AnimateFlopToRiver()
        {
            this.DominoAnimate(
                () => this.FlopHandsStackPanel.AnimateCardImageOne(),
                () => this.DominoAnimate(
                    () => this.FlopHandsStackPanel.AnimateCardImageTwo(),
                    () => this.DominoAnimate(
                        () => FlopHandsStackPanel.AnimateCardImageThree(),
                        () => this.DominoAnimate(
                            () => FlopHandsStackPanel.AnimateCardImageFour(),
                            () => FlopHandsStackPanel.AnimateCardImageFive()))));
        }

        private void DominoAnimate(Action myself, Action neighbor)
        {
            myself();

            Scheduler.Dispatcher.Schedule(
                () => this.BeginInvoke(neighbor),
                TimeSpan.FromMilliseconds(100));
        }

        #endregion

        #endregion //Private Methods
    }
}